www.gusucode.com > VC编写的串口调试软件 > VC编写的串口调试软件,内含Modbus协议类 支持对Modbus通讯调试/Modbus串口调试软件1.0/com/MsgPSPWnd.cpp

    // MsgPumpWnd.cpp : implementation file
//

#include "stdafx.h"
#include "MsgPSPWnd.h"
#include "..\com\FOData.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMsgPSPWnd

CMsgPSPWnd::CMsgPSPWnd()
{
	TRACE("CMsgPSPWnd--构造--0x%x\n",this);
	m_strAlias="串口通讯";
	m_unMemFileSize=0;

	m_pThread=NULL;					//线程
	m_pProtocal=NULL;
	m_pSerialPort=NULL;
	
	m_pReData=NULL;
	m_pCurData=NULL;
	m_nCurPos=NULL;
	m_nNextPos=NULL;				//下一条记录

	m_bWriteValue=false;
	m_dwStartCalcTime=0;


	
	m_nRecieveState=1;					//数据接收状态,1:正确,2:要求重发

	m_unTimeRelay=1000;					//延时ms
	m_unReSendNum=0;					//重发次数
	m_unCheckOtherCommTime=0;

	m_ucRcvTxt[0]='\n';			//接收缓冲区
	m_unRcvLen=0;					//接收长度

}

UINT	CMsgPSPWnd::m_unCommErr=0;						//连续通讯错误
UINT	CMsgPSPWnd::m_unCommErrCount=30;
int 	CMsgPSPWnd::m_nCommErrTime=0;					//错误计时
int 	CMsgPSPWnd::m_nCommErrTimeCount=120000;			//错误计时数:如果在计时时段内通讯,当m_unCommErr>=m_unCommErrCount,则无需通讯重新开始

UINT	CMsgPSPWnd::m_unCommSucceed=0;					//连续通讯成功次数,如果连续通讯次数达到100次,则通讯错误清空
UINT	CMsgPSPWnd::m_unCommSucceedCount=100;			//100次,则通讯错误清空

CMsgPSPWnd::~CMsgPSPWnd()
{
	TRACE("CMsgPSPWnd--析构--0x%x\n",this);

	ReleaseResource();

}


BEGIN_MESSAGE_MAP(CMsgPSPWnd, CPlugPPBase)
	//{{AFX_MSG_MAP(CMsgPSPWnd)
	ON_MESSAGE(WM_COMM_RXCHAR, OnCommRXChar)
	ON_MESSAGE(WM_COMM_CTS_DETECTED, OnCommCTSDetected)
	ON_MESSAGE(WM_COMM_BREAK_DETECTED, OnCommBreadDetected)
	ON_MESSAGE(WM_COMM_DSR_DETECTED, OnCommDSRDetected)
	ON_MESSAGE(WM_COMM_ERR_DETECTED, OnCommERRDetected)
	ON_MESSAGE(WM_COMM_RING_DETECTED, OnCommRingDetected)
	ON_MESSAGE(WM_COMM_RXFLAG_DETECTED, OnCommRXFlagDetected)
	ON_MESSAGE(WM_COMM_TXEMPTY_DETECTED, OnCommTXEmptyDetected)
	ON_MESSAGE(WM_COMM_RLSD_DETECTED, OnCommRLSDDected)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CMsgPSPWnd message handlers
CComData CMsgPSPWnd::GetData(const POSITION& pos)
{
	CComData* pComData=(CComData*)m_listData.GetAt(pos);

	return *pComData;
}

CString CMsgPSPWnd::GetProtocalName() 
{
	CreateProtocal();

	if(m_pProtocal)
		return m_pProtocal->m_strPrtName;
//		strcpy((LPTSTR)(LPCTSTR)rString,(LPTSTR)(LPCTSTR)m_pProtocal->m_strPrtName);
//	else
//		strcpy((LPTSTR)(LPCTSTR)rString,"无");
	CString str="未知协议";
	return str;
}

CString CMsgPSPWnd::GetValue(const POSITION &pos)
{
	CComData* pComData=(CComData*)m_listData.GetAt(pos);

	
	return pComData->m_strRegValue;

}

void CMsgPSPWnd::Release()
{

	TRACE("\n**********协议驱动:%s\n","ModBus");
	try{
		delete this;
	}catch(...)
	{
		TRACE("\n*****CMsgPSPWnd::Release()\n");
	}
}


BOOL CMsgPSPWnd::Run (HWND hWndParent)
{	
	CString strInfo="I CMsgPSPWnd";
	//1、连接协议
	CreateProtocal();
	if (NULL==m_pProtocal)
	{
		strInfo.Format ("协议%s创建失败",m_pProtocal->m_strPrtName);
		CWnd wnd;
		wnd.Attach (hWndParent);
		wnd.SendMessage(WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo));			//不能用邮寄方式PostMessage
		wnd.Detach ();

		return FALSE;
	}

	//2、创建窗口
	ASSERT(NULL==m_hWnd);			//已经被调用过一次
	BOOL bT=CreateEx(0,				//dwExStyle						//---方法2
				AfxRegisterWndClass(0),		//lpszClassName
				NULL,						//lpszWindowName
				WS_CHILD,//WS_POPUP,WS_BORDER|WS_POPUP,			//dwStyle
				0,0,0,0,
				hWndParent,					//hwndParent
				0);							//nIDorHMenu
	
//		return bT;
	if (FALSE==bT)
	{
		TRACE("*********** CMsgPSPWnd--窗口创建失败 %s *********\n",m_strAlias);

		strInfo.Format ("%s--窗口创建失败",m_pProtocal->m_strPrtName);
		CWnd wnd;
		wnd.Attach (hWndParent);
		wnd.SendMessage(WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo));			//不能用邮寄方式PostMessage
		wnd.Detach ();

		delete m_pProtocal;

		return bT;
	}

	//3、创建端口
	m_pSerialPort=new CSerialPort;
	if(NULL==m_pSerialPort)
		return FALSE;

	//读取端口设定信息
	ReadPortInf();

	if(	m_pSerialPort->InitPort(this, 
				m_SPData.uPortNum,
				m_SPData.uBaud,
				m_SPData.cParity,
				m_SPData.uDataBits,
				m_SPData.uStopBits,
				m_SPData.dwCommEvents,
				m_SPData.nBufferSize))
	{
		strInfo.Format ("%s打开端口%d",m_pProtocal->m_strPrtName,m_SPData.uPortNum);
		GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo) );
		
		m_pSerialPort->StartMonitoring();
		TRACE("*********** FIND PORT %d *********0x%x\n",m_SPData.uPortNum,m_pSerialPort);
	}
	else
	{
		strInfo.Format ("%s打开端口%d失败",m_pProtocal->m_strPrtName,m_SPData.uPortNum);
		GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo) );
		// port not found
		TRACE("***********NO FIND PORT %d *********\n",m_SPData.uPortNum);
		delete m_pProtocal;
		return FALSE;
	}
	

	//4、读取数据
	ReadIO();

	strInfo.Format ("%s加载数据成功",m_pProtocal->m_strPrtName,m_SPData.uPortNum);
	GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo) );

	//5、创建内存文件
	CreateMemFile();
	SetTimer(TIMER_EVENT_WM,500,NULL);

	//5、启动线程
	if (!(m_pThread = AfxBeginThread(RunPump,this)))
	{
		delete m_pProtocal;
		return FALSE;
	}

	strInfo.Format ("%s启动数据通讯",m_pProtocal->m_strPrtName);
	GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo) );

	return bT;
}


UINT CMsgPSPWnd::RunPump (LPVOID pParam )
{
	//先休眠2s,便于程序启动完毕
//	::Sleep (2000);
	CMsgPSPWnd* pMsgPump=(CMsgPSPWnd*) pParam;

	if(NULL==pMsgPump->m_pProtocal)
		{TRACE("CMsgPSPWnd::RunPump()----通信协议未指定! \n");}
	//1、得到首记录
	pMsgPump->m_nNextPos=pMsgPump->m_listData.GetHeadPosition();
	if(NULL==pMsgPump->m_nNextPos)
		return 1;	//没有记录
	try
	{
	while(pMsgPump)
	{
		//-----------------------------------------------------------------------------------------------------------------------------
		//1、检查是否需要等待发送-------时间轮片机制(多主站协议)----2003.12.21
		if(pMsgPump->IsWaitSend())
			continue;

		//----------------------------------------------------------------
		//2、超时处理
		if(pMsgPump->m_pCurData)
		{
			if(pMsgPump->m_unTimeRelay<=pMsgPump->GetCalcTime()	//通讯超时
				&& 0==pMsgPump->m_nRecieveState)
			{	//发送一个超时消息

				//发送已经接收到的信息
				if(0<pMsgPump->m_pCurData->m_unRcvLen )
					pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('c'),LPARAM(&pMsgPump->GetRevInfo()) );
			
				//
				if(2>pMsgPump->m_unReSendNum++)
				{
					pMsgPump->m_unCommSucceed=0;
	//*
					TRACE("CMsgPSPWnd::RunPump 超时重发=%d\t寄存器类型:% 6d\t寄存器地址:% 6d\t协议类型:\n",
					pMsgPump->m_unReSendNum,pMsgPump->m_pCurData->m_unRegType,pMsgPump->m_pCurData->m_unRegAddr);
					TRACE("CMsgPSPWnd::RunPump 超时%d\t延时%d\t%d\n",pMsgPump->GetCalcTime(),pMsgPump->m_unTimeRelay,::GetTickCount());
	//*/
					//重发清除以前接收到的数据m_CurData.ClearRData();
					//协议接收状态为等待状态
					pMsgPump->m_pProtocal->Init ();

					if(pMsgPump->m_bWriteValue)
					{
						pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('W'),LPARAM(&pMsgPump->GetSendInfo()) );
					}
					else
						pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('R'),LPARAM(&pMsgPump->GetSendInfo()) );
					pMsgPump->m_pSerialPort->WriteToPort (pMsgPump->m_pCurData->m_ucProtocalTxt,pMsgPump->m_pCurData->m_unDataLen );
					pMsgPump->StartCalcTime ();

				}
				else	//多次从发后仍通讯失败
				{	
					//恢复上次数据
					if(pMsgPump->m_pCurData->m_hClientWnd)	//写操作
					{
						//---------------------------------------------------------------------------------------------------------
						//回传数据
						char cInfo[100];
						CString strInfo;
						sprintf(cInfo,"%s  %s", pMsgPump->m_pCurData->m_strAlias,COM_WRTIE_FALSE);
						//---------------------------------------------------------------------------------------------------------
						COPYDATASTRUCT CpyData;
						CpyData.lpData =&cInfo[0];
						CpyData.cbData =sizeof(cInfo)/sizeof(char);

						WPARAM wParam = (WPARAM) (HWND)pMsgPump->m_hWnd ;            // handle of sending window 
						LPARAM lParam = (LPARAM) & CpyData; // pointer to structure with data 

						CWnd wnd;
						wnd.Attach (pMsgPump->m_pCurData->m_hClientWnd);
						wnd.SendMessage(WM_COPYDATA,wParam,lParam);			//不能用邮寄方式PostMessage
						wnd.Detach ();

					}
					
					//发送下一条信息试试
					pMsgPump->m_unReSendNum=0;		//重发次数
					pMsgPump->m_nRecieveState=1;
				}

				//可能系统通讯中断比较长或通讯失败较多,则重新建立通讯
				if(IsMoreCommErr())
				{
					pMsgPump->SetTimer(1,3000,NULL);
					return 1;
				}
			}
		}
		//----------------------------------------------------------------
		//3、发送处理
		switch(pMsgPump->m_nRecieveState)
		{
		case 0:		//正在接收记录
			break;
		case 1:		//上一条数据接收完毕,发送新数据
			IsMoreSucceed();	//多次通讯成功,清空计时错误


			pMsgPump->m_unReSendNum=0;		//重发次数
			//一、检查有无需要立即发送的数据----如果写数据失败,没有处理,因该再恢复原值?
			if(pMsgPump->m_pReData)
			{	//说明上次进行了写操作,将写操作相关寄存器的值对应的数据读取一遍,可以加快刷新速度
				pMsgPump->m_pCurData=pMsgPump->m_pReData;
				pMsgPump->m_pReData=NULL;
				pMsgPump->m_bWriteValue =false;
			}
			else
			{
				if(NULL!=pMsgPump->m_listNowData.GetHeadPosition())
				{
					pMsgPump->m_pCurData=(CComData*)pMsgPump->m_listNowData.RemoveHead ();
					pMsgPump->m_bWriteValue =true;
				}
				else
				{//发送读取记录信息
					int nGood=0;
					int nPriority=0;
					do{
						if(NULL==pMsgPump->m_nNextPos)
						{
							//更新数据 
							pMsgPump->WriteMemData();
							//
							pMsgPump->m_nNextPos=pMsgPump->m_listData.GetHeadPosition();
							if(100<++pMsgPump->m_unCycleTime)		//循环次数
								pMsgPump->m_unCycleTime=1;
							if(nGood++>2)
								break;		//说明没有发送的数据,可能完全写操作
						}
						
						pMsgPump->m_nCurPos=pMsgPump->m_nNextPos;
						pMsgPump->m_pCurData=(CComData*)pMsgPump->m_listData.GetNext (pMsgPump->m_nNextPos);
						nPriority=pMsgPump->m_pCurData->m_unPriority;
						nPriority=nPriority==0?5:nPriority;

					}while(pMsgPump->m_unCycleTime%nPriority!=0
						&& pMsgPump->m_unCycleTime>3
						);

					pMsgPump->m_bWriteValue =false;
				}
			}
			//二、发送新数据
			//1、得到数据
			//2、翻译数据
			::Sleep (10);

			//翻译通讯协议
			pMsgPump->m_pProtocal->Decoding(*pMsgPump->m_pCurData);

		case 2:		//再发送一次//协议接收状态为等待状态
		case 3:		//校验错误,要求重发一次//协议接收状态为等待状态
			
			if(pMsgPump->m_bWriteValue)
				pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('W'),LPARAM(&pMsgPump->GetSendInfo()) );
			else
				pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('R'),LPARAM(&pMsgPump->GetSendInfo()) );

			pMsgPump->m_pProtocal->Init ();
			pMsgPump->m_pSerialPort->WriteToPort (pMsgPump->m_pCurData->m_ucProtocalTxt,pMsgPump->m_pCurData->m_unDataLen );
			pMsgPump->m_nRecieveState=0;
			pMsgPump->StartCalcTime ();
			break;
		default:
			TRACE("CMsgPSPWnd::RunPump()----接收状态错误! \n");
			pMsgPump->m_nRecieveState=1;
			break;
		}
	}	//while

	}
	catch(CString strEx)
	{
		CString strErr;
		strErr.Format ("RumPump()--%s:%s",pMsgPump->m_strAlias,strEx);
		pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('E'),LPARAM(&strErr) );
		TRACE("%s\n",strEx);
	}
	catch(char* szException)
	{
		CString strErr;
		strErr.Format ("RumPump()--%s:%s",pMsgPump->m_strAlias,szException);
		pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('E'),LPARAM(&strErr) );
		TRACE("%s\n",szException);
	}
	catch(...)
	{
		CString strErr;
		strErr.Format ("RumPump()--%s:发生不知道的错误!",pMsgPump->m_strAlias);
		pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('E'),LPARAM(&strErr) );

		TRACE("CMsgPSPWnd::RunPump()----发生不知道的错误! \n");
	}
	//退出线程
	pMsgPump->m_pThread=NULL;
	return 1;
}

// A character was received and placed in the input buffer. 
LONG CMsgPSPWnd::OnCommRXChar(WPARAM ch, LPARAM port)
{
	if (port <= 0 || port > 4)
		return -1;
	if (NULL==m_pProtocal)
	{
		TRACE("<*>*<*>*<*>  m_pProtocal==NULL\n");
		return -1;
	}

	try
	{
		CString strValue;
		m_ucRcvTxt[m_unRcvLen++]=ch;			//接收缓冲区
		int nReceiveState=m_pProtocal->ReceiveByte ((unsigned char&) ch);

		switch(nReceiveState)
		{
		case 0:
			{
				//正在接收
				break;
			}
		case 1:
			{
				//字符接收完毕
				m_nRecieveState=1;

				//更新旧值
				m_pCurData->m_strOldRegValue =m_pCurData->m_strRegValue ;
	#ifdef _DEBUG
	//			if(m_bWriteValue)
				TRACE("RegAddr=%d  RegValue=%s\n",m_pCurData->m_unRegAddr,m_pCurData->m_strRegValue);
	#endif
				//将当前结果存放在列表中
				GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('C'),LPARAM(&GetRevInfo()) );
				m_unRcvLen=0;
				//写操作
				if(m_pCurData->m_hClientWnd)
				{
					char cInfo[100];
					CString strInfo;
					sprintf(cInfo,"%s  %s", m_pCurData->m_strAlias ,m_pCurData->m_strRegValue);

					COPYDATASTRUCT CpyData;
					CpyData.lpData =&cInfo[0];
					CpyData.cbData =sizeof(cInfo)/sizeof(char);

					WPARAM wParam = (WPARAM) (HWND) m_hWnd ;            // handle of sending window 
					LPARAM lParam = (LPARAM) & CpyData; // pointer to structure with data 

					CWnd wnd;
					wnd.Attach (m_pCurData->m_hClientWnd);
					wnd.SendMessage(WM_COPYDATA,wParam,lParam);			//不能用邮寄方式PostMessage
					wnd.Detach ();
					//
					//写成功
					//---------------------------------------------------------------------------------------------------------
					m_pReData=m_pCurData->m_pReData;
					delete m_pCurData;
					m_pCurData=NULL;
					m_bWriteValue=false;

					//---------------------------------------------------------------------------------------------------------
				}
					
				if (0<m_pCurData->m_unReSend)
					m_nRecieveState=2;
				
				//通讯连接正常
				m_unCommErr=0;

	//			TRACE("CMsgPSPWnd::OnCommRXChar()----接收状态正确! 寄存器类型:%s\t地址:%s=%s\n",
	//				m_CurData.m_strRegType,m_CurData.m_strRegAddr,m_CurData.m_strRegValue );
				break;
			}
		case 2:		//是否要重发,由协议自己处理
			{
				//要求重发送一次
				GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('c'),LPARAM(&GetRevInfo()) );
				m_unRcvLen=0;
				break;
			}
		case 4:		//数据项为空,可能有其他设备在通讯
			{
//				GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('C'),LPARAM(&GetRevInfo()) );
				m_unRcvLen=0;
				int nTime=m_unCheckOtherCommTime;
				m_unCheckOtherCommTime=::GetTickCount();

//			TRACE("CMsgPSPWnd::OnCommRXChar()--%d-时间间隔:%d-其他设备在通讯! \n",m_unCheckOtherCommTime,m_unCheckOtherCommTime-nTime);
			break;	
			}
		default:	//不知道的信息
			{
				TRACE("CMsgPSPWnd::OnCommRXChar()----接收状态错误! \n");
				GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('c'),LPARAM(&GetRevInfo()) );
				m_unRcvLen=0;
			}
		}
	}
	catch(char* szException)
	{
		TRACE("%s\n",szException);
	}
	catch(CString strErr)
	{
		TRACE("%s\n",strErr);
		GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('c'),LPARAM(&GetRevInfo()) );
		m_unRcvLen=0;
		GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('E'),LPARAM(&strErr) );
	}
	catch(...)
	{
		;
	}
	return 0;
}

// The CTS (clear-to-send) signal changed state. 
LONG CMsgPSPWnd::OnCommCTSDetected(WPARAM wparam, LPARAM port)
{
	if (port <= 0 || port > 4)
		return -1;
/*
	CString string;
	string = "Clear To Send";
	CString strEnter;
	strEnter.Insert (0,10);
	strEnter.Insert (0,13);
	m_strReceiveTxt=m_strReceiveTxt+strEnter;
	m_strReceiveTxt=m_strReceiveTxt+string;
	m_strReceiveTxt=m_strReceiveTxt+strEnter;


	UpdateData(FALSE);
//*/
//	TRACE("CCCommPLCDlg::OnCommCTSDetected()\n");
	 return 0;
}

// A break was detected on input.
LONG CMsgPSPWnd::OnCommBreadDetected(WPARAM wparam, LPARAM lparam)
{
	TRACE("CCCommPLCDlg::OnCommBreadDetected()\n");
	 return 0;
}

// The DSR (data-set-ready) signal changed state.
LONG CMsgPSPWnd::OnCommDSRDetected(WPARAM wparam, LPARAM lparam)	
{
	TRACE("CCCommPLCDlg::OnCommDSRDetected()\n");
	 return 0;
}

// A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. 	
LONG CMsgPSPWnd::OnCommERRDetected(WPARAM wparam, LPARAM lparam)	
{
	TRACE("CCCommPLCDlg::OnCommERRDetected()\n");
	 return 0;
}
	 
// A ring indicator was detected. 
LONG CMsgPSPWnd::OnCommRingDetected(WPARAM wparam, LPARAM lparam)	
{
	TRACE("CCCommPLCDlg::OnCommRingDetected()\n");
	 return 0;
}

// The event character was received and placed in the input buffer.  		
LONG CMsgPSPWnd::OnCommRXFlagDetected(WPARAM wparam, LPARAM lparam)	
{
	TRACE("CCCommPLCDlg::OnCommRXFlagDetected()\n");
	 return 0;
}

// The last character in the output buffer was sent.	
LONG CMsgPSPWnd::OnCommTXEmptyDetected(WPARAM wparam, LPARAM lparam)	
{
	TRACE("CCCommPLCDlg::OnCommTXEmptyDetected)\n");
	 return 0;
}

// The RLSD (receive-line-signal-detect) signal changed state.
LONG CMsgPSPWnd::OnCommRLSDDected(WPARAM wparam, LPARAM lparam)		
{
	TRACE("CCCommPLCDlg::OnCommRLSDDected()\n");
	 return 0;
}

UINT CMsgPSPWnd::GetCalcTime()	//从上次调用StartCalcTime()至目前为止的毫秒时间间隔
{
	if(0==m_dwStartCalcTime)	//刚开始
		return 0;
	DWORD dwEnd=::GetTickCount() ;
	m_nCommErrTime+=dwEnd-m_dwStartCalcTime;
	return dwEnd-m_dwStartCalcTime;
	
}

void CMsgPSPWnd::StartCalcTime()
{
	m_dwStartCalcTime=::GetTickCount() ;
}


void CMsgPSPWnd::SendInfo(HWND hWnd,CString &strInfo)
{
	char cInfo[100];
//	sprintf(cInfo,"%s",strInfo);
	strcpy(cInfo,strInfo);

	COPYDATASTRUCT CpyData;
	CpyData.lpData =&cInfo[0];
	CpyData.cbData =sizeof(cInfo)/sizeof(char);

	WPARAM wParam = (WPARAM) (HWND) m_hWnd ;            // handle of sending window 
	LPARAM lParam = (LPARAM) & CpyData; // pointer to structure with data 

	CWnd wnd;
	wnd.Attach (hWnd);
	wnd.SendMessage(WM_COPYDATA,wParam,lParam);			//不能用邮寄方式PostMessage
	wnd.Detach ();
}

BOOL CMsgPSPWnd::SetValue(const HWND hWndSend,const LPTSTR  strInfo)	//需要立即更新:数据操作
{	//根据协议,自行修改
	char cName[100];
	char cValue[500];

	sscanf(strInfo,"%s %s",cName,cValue);
	CComData * pData;
	POSITION pos=m_mapResource.GetStartPosition ();
	if(m_mapResource.Lookup(cName,(void*&)pData))
	{
		CComData* pComData=new CComData;
		*pComData=*pData;
		pComData->m_unRegType=0x10;		//只支持多个寄存器写

		pComData->m_strRegValue =cValue;
		pComData->m_hClientWnd =hWndSend;
		pComData->m_pReData =GetRelation(pComData);

		m_listNowData.AddTail (pComData);

		return TRUE;
	}

	return FALSE;
	TRACE("CMsgPSPWnd::SetValue(%s)\n",strInfo);
}

void CMsgPSPWnd::SetPort(UINT portnr, UINT baud, char parity, UINT databits, UINT stopsbits,DWORD dwCommEvents,UINT nBufferSize)
{
	m_SPData.uPortNum=portnr;
	m_SPData.uBaud=baud;
	m_SPData.cParity=parity;
	m_SPData.uDataBits=databits;
	m_SPData.uStopBits=stopsbits;
	m_SPData.dwCommEvents=dwCommEvents;
	m_SPData.nBufferSize=nBufferSize;
}

POSITION CMsgPSPWnd::AddData(CComData &comData)
{
	return m_listData.AddTail(&comData);
}

void CMsgPSPWnd::ReadPortInf()
{
	TRY
	{
		UINT portnr;
		UINT baud;
		char parity;
		UINT databits;
		UINT stopsbits;
		DWORD dwCommEvents;
		UINT nBufferSize;

		CFOData foData;
		m_unMemFileSize=foData.ReadPortInf(
			m_strAlias,
			portnr,
			baud,
			parity,
			databits,
			stopsbits,
			dwCommEvents,
			nBufferSize
			);

		SetPort(portnr,baud,parity,databits,stopsbits);
	}
	CATCH( CFileException, e )
	{
	   #ifdef _DEBUG
		  afxDump << "File could not be opened " << e->m_cause << "\n";
	   #endif
	}
	END_CATCH
}

void CMsgPSPWnd::OnTimer(UINT nIDEvent) 
{
	switch(nIDEvent)
	{
	case TIMER_EVENT_SP:
		{
	
			if(	m_pSerialPort->InitPort(this, 
						m_SPData.uPortNum,
						m_SPData.uBaud,
						m_SPData.cParity,
						m_SPData.uDataBits,
						m_SPData.uStopBits,
						m_SPData.dwCommEvents,
						m_SPData.nBufferSize))
			{
				m_pSerialPort->StartMonitoring();
				TRACE("*********** FIND PORT %d *********\n",m_SPData.uPortNum);
			}
			else
			{
				// port not found
				TRACE("***********NO FIND PORT %d *********\n",m_SPData.uPortNum);
				return ;
			}
			//4、启动线程
			BeginThread();

			KillTimer(nIDEvent);
			break;
		}
	case TIMER_EVENT_WM:
		{
			WriteMemData();
			break;
		}
	default:
		{
			;
		}
	}
	CWnd::OnTimer(nIDEvent);

}

void CMsgPSPWnd::WriteMemData()
{
//	return;
	if(m_pMemFile)
	{
//		TRACE("CMsgPSPWnd::WriteMemFile()\n");

		m_pMemFile->SeekToBegin();

		//*
		//数据
		//-------------------------------------------------------------------------
		//数据总记录条数
		int nCount=0;
//		m_pMemFile->Seek(4,CFile::begin);

		//写数据
		POSITION pos=m_listData.GetHeadPosition ();
		CComData* pData;
		try{
		while(pos)
		{
			pData=(CComData*)m_listData.GetNext (pos);
			pData->WriteMemData (m_pMemFile);

//			TRACE("WriteMemData()---%d\n",m_pMemFile->GetPosition ());
			nCount++;
		}
//		m_pMemFile->SeekToBegin();
//		m_pMemFile->Write( &nCount,sizeof(int));
		}
		catch(...)
		{
			TRACE("CMsgPSPWnd::WriteMemData()--Error\n");
		}
		//-------------------------------------------------------------------------
	}
}

void CMsgPSPWnd::ReadIO()
{
	CFOData foData;
	foData.SearchComData(m_strAlias,m_mapResource);
 
 	Optimize();	
}

void CMsgPSPWnd::ReadMemData()
{
	if(NULL==m_pMemFile)
		return;
/*
	POSITION pos=m_listData.GetHeadPosition ();
	while(pos)
	{
		CComData comData=m_listData.GetNext (pos);
		comData.ReadMemData (m_pMemFile);
	}
//*/
	//创建内存文件
	CreateMemFile();
}

BOOL CMsgPSPWnd::CreateMemFile()
{
	/*
	HANDLE CreateFileMapping(
	HANDLE hFile,    // 映射文件的句柄,
	//设为0xFFFFFFFF以创建一个进程间共享的对象
	LPSECURITY_ATTRIBUTES lpFileMappingAttributes,    // 安全属性
	DWORD flProtect,    // 保护方式
	DWORD dwMaximumSizeHigh,    //对象的大小
	DWORD dwMaximumSizeLow,   
	LPCTSTR lpName     // 必须为映射文件命名
	);
	//*/
	/*
	LPVOID MapViewOfFile(
	  HANDLE hFileMappingObject,  // file-mapping object to map into 
								  // address space
	  DWORD dwDesiredAccess,      // access mode
	  DWORD dwFileOffsetHigh,     // high-order 32 bits of file offset
	  DWORD dwFileOffsetLow,      // low-order 32 bits of file offset
	  DWORD dwNumberOfBytesToMap  // number of bytes to map
	);
	//*/
	CString strFileName;
	strFileName.Format ("%s.mem",m_strAlias);

 	//1、创建一个名为MySharedMem的长度为4096字节的有名映射文件:
	HANDLE hMySharedMapFile=CreateFileMapping((HANDLE)0xFFFFFFFF,
												NULL,
												PAGE_READWRITE,
												0,
												0x1000,
												strFileName);
	if(NULL==hMySharedMapFile)
		return FALSE;

	//2、并映射缓存区视图:
	LPSTR pszMySharedMapView=(LPSTR)MapViewOfFile(hMySharedMapFile,
													FILE_MAP_READ|FILE_MAP_WRITE,
													0,0,0);

	if(NULL==pszMySharedMapView)
		return FALSE;

	//读取内存文件申请大小
	ReadMDFSize();
	ASSERT(0<m_unMemFileSize);

	//3、使其成为内存文件操作
	m_pMemFile=new CMemFile((unsigned char*)pszMySharedMapView, m_unMemFileSize, 0 );

	TRACE("CMsgPSPWnd::CreateMemFile()--%s--Size:%d\n",strFileName,m_unMemFileSize);
//	char cLen[4];
//	m_pMemFile->Write( cLen,4);
	return TRUE;
	/*
	//客户端访问方式
	//1、访问共享对象,需要获得对象名并调用OpenFileMapping函数。
	HANDLE hMySharedMapFile=OpenFileMapping(FILE_MAP_WRITE,
											FALSE,
											GetIOFileName());
	if(NULL==hMySharedMapFile)
		return;

	//2、并映射缓存区视图:
	LPSTR pszMySharedMapView=(LPSTR)MapViewOfFile(hMySharedMapFile,
													FILE_MAP_READ,
													0,0,0);
	if(NULL==pszMySharedMapView)
		return;

	//3、使其成为内存文件操作
	m_pMemFile=new CMemFile((unsigned char*)pszMySharedMapView, 4096, 0 );

	//4、读数据
	   char c[100];
	   CString strReadTxt;
	   m_pMemFile->SeekToBegin ();
	   m_pMemFile->Read (&c[0],100);

		strcpy((LPTSTR)(LPCTSTR)strReadTxt,c);

	//*/

}



void CMsgPSPWnd::CloseFile()
{
	//当用户进程结束使用共享内存后,调用UnmapViewOfFile函数以取消其地址空间内的视图:
	if(NULL==m_pMemFile)
		return;

	LPSTR pszMySharedMapView=(LPSTR)m_pMemFile->Detach ();
	delete m_pMemFile;
	m_pMemFile=NULL;

	if (!UnmapViewOfFile(pszMySharedMapView))
		{ AfxMessageBox("could not unmap view of file"); }

}

void CMsgPSPWnd::ReadMDFSize()	//读取内存文件大小
{
	CFOData foData;
	m_unMemFileSize=foData.ReadMDFSize (m_strAlias);
}

BOOL CMsgPSPWnd::IsCommErrTime()	//是否在通讯错误时段内,如果在,则关闭端口,重新启动
{
	TRACE("CMsgPSPWnd::IsCommErrTime()  m_nCommErrTimeCount=%d,m_nCommErrTime=%d\n",m_nCommErrTimeCount,m_nCommErrTime);
	int nCommErrTime=m_nCommErrTime;
	m_nCommErrTime=0;
	return m_nCommErrTimeCount-nCommErrTime;
}

bool CMsgPSPWnd::IsMoreCommErr()	//可能系统通讯中断比较长或通讯失败较多,则重新建立通讯
{
	if(++m_unCommErr>=m_unCommErrCount)
	{
		m_unCommErr=0;
		if(IsCommErrTime ()>0)
		{
			return true;	//要求重新建立通讯
		}
	}

	return false;
}

bool CMsgPSPWnd::IsMoreSucceed()
{
	if(++m_unCommSucceed>=m_unCommSucceedCount)
	{
		//多次通讯成功,清空计时错误
		m_unCommErr=0;
		m_nCommErrTime=0;
		
		return true;
	}

	return false;
}

int CMsgPSPWnd::CalcuDataSize()
{

	return 0;
}

bool CMsgPSPWnd::IsWaitSend()
{
	return false;
}

void CMsgPSPWnd::BeginThread()
{
	if (!(m_pThread = AfxBeginThread(RunPump,this)))
		return ;
}

void CMsgPSPWnd::Optimize()
{	//不做任何优化
	POSITION pos=m_mapResource.GetStartPosition ();
	CString strKey;
	CComData * pData;
	while(pos)
	{
		m_mapResource.GetNextAssoc (pos,strKey,(void*&)pData);
		
		CComData * pComData=new CComData;
		*pComData=*pData;
		m_listData.AddTail (pComData);
	}
}

CString CMsgPSPWnd::GetHexInfo(unsigned char* pucbuf,unsigned int unLen) const
{
	CString strBHex;
	CString strHex;
	for(UINT n=0;n<unLen;n++)
	{
		strBHex.Format (" %02x",pucbuf[n]);
		strHex+=strBHex;
	}
	return strHex;
}

CString CMsgPSPWnd::GetRevInfo()
{
	if(m_pCurData)
	{
		CString strInfo;
		strInfo.Format ("%20s %s",
			m_pCurData->m_strAlias,
			GetHexInfo(&m_ucRcvTxt[0],m_unRcvLen)
			);
		return strInfo;
	}

	return 	GetHexInfo(&m_ucRcvTxt[0],m_unRcvLen);
}

CString CMsgPSPWnd::GetSendInfo()
{
	CString strInfo="**";
	if(m_pCurData)
	{
		strInfo.Format ("%20s %s",
			m_pCurData->m_strAlias,
			GetHexInfo(&m_pCurData->m_ucProtocalTxt[0],m_pCurData->m_unDataLen)
			);
	}
	else
	{
		TRACE("CMsgPSPWnd::GetSendInfo()--Error\n");
	}
	TRACE("GetSendInfo()---%s\n",strInfo);
	return strInfo;
}


void CMsgPSPWnd::PostNcDestroy() 
{
	// TODO: Add your specialized code here and/or call the base class
	if(m_pThread)
	{
//		::WaitForSingleObject(m_pThread,1000);
		DWORD dwExitCode=0;
//		TerminateThread(m_pThread,dwExitCode);
//		ASSERT(NULL!=TerminateThread(m_pThread->m_hThread,dwExitCode));
		TerminateThread(m_pThread->m_hThread,dwExitCode);

		::GetExitCodeThread(m_pThread->m_hThread,&dwExitCode);
		if(dwExitCode==STILL_ACTIVE)
			TRACE("--CMsgPSPWnd---still_active\n");
		delete m_pThread;
		m_pThread=NULL;
	}
	CPlugPPBase::PostNcDestroy();

	ReleaseResource();
}

CComData* CMsgPSPWnd::GetRelation(CComData* pData)const
{
	POSITION posOpt=m_listData.GetHeadPosition ();

	while(posOpt)
	{
		CComData* pComData=(CComData*)m_listData.GetNext (posOpt);
		if(pComData->m_nStationNum ==pData->m_nStationNum
		&& pComData->m_unRegType ==pData->m_unRegType
		&& (pComData->m_unRegAddr <=pData->m_unRegAddr
		  &&pComData->m_unRegAddr+pComData->m_unRegCount>=pData->m_unRegAddr+pData->m_unRegCount)
		)
		{
			return pComData;
		}
	}
	return NULL;
}

void CMsgPSPWnd::ReleaseResource()
{
	if(m_pProtocal)
	{
		delete m_pProtocal;
		m_pProtocal=NULL;
	}
	if(m_pSerialPort)
	{
		delete m_pSerialPort;
		m_pSerialPort=NULL;
	}

	POSITION pos=m_mapResource.GetStartPosition ();
	CString strKey;
	CComData * pData;
	while(pos)
	{
		m_mapResource.GetNextAssoc (pos,strKey,(void*&)pData);
		delete pData;
	}
	m_mapResource.RemoveAll ();

	pos=m_listData.GetHeadPosition ();
	while(pos)
	{
		pData=(CComData*)m_listData.GetNext (pos);
		delete pData;
	}
	m_listData.RemoveAll ();

	CloseFile();
}